<?php

namespace Frieza\Modules\Position\Controllers;

use App\Http\Controllers\Controller;
use App\Pockets\GridDataModel;
use Biz\cache\advertisement\CPositionBaseInfo;
use Biz\model\advertisement\MPosition;
use Biz\model\advertisement\MPositionBaseInfo;
use Biz\model\advertisement\MPositionProject;
use Biz\model\advertisement\MPositionProjectRelations;
use Biz\model\advertisement\MPositionRules;
use Biz\service\adCalendar\AdPosition;
use Biz\service\advertisement\AdConfManagement;
use Biz\service\advertisement\AdPositionManagement;
use Biz\service\advertisement\apiModule\BaseModule;
use Doraemon\service\position\AdmOperationModule;
use Doraemon\service\position\ConstInterface;
use Doraemon\service\position\PositionConstInterface;
use Doraemon\service\position\PositionModule;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Encore\Admin\Widgets\Form;
use Encore\Admin\Widgets\Tab;
use Encore\Admin\Widgets\Table;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\MessageBag;

abstract class BaseController extends Controller
{
    const REDIRECT_CODE = 1024;
    public $id = 0;
    public $preview = false;
    public $relId = 0;
    public $positionId = 0;
    protected $positionConf = [];
    public $en_name = '';
    public $tabName = '列表信息';
    public $moduleTitle = '未命名';
    public $moduleTitle4List = '未命名';
    public $moduleRel = '未命名';
    public $moduleTab = 1;
    public $saveRoute = '';
    public $listRoute = '';
    public $copyRoute = '';
    public $previewRoute = 'preview';
    public $viewRoute = 'view';
    public $relation = [];
    public $project = null;
    public $message = [];
    public $is_admin = false;
    public $is_operator = true;
    public $base_field_share = MPositionBaseInfo::IS_SHARE;
    public $base_field_pos = 0;
    public $base_field_ext_type = 0;
    public $base_field_close_type = MPositionBaseInfo::CLOSE_TYPE_NONE;
    public $filter_field_pos = true;
    public $filter_field_uid = true;
    public $conf_message = [];
    protected array $bannerAllowLink = [];
    protected array $cardAllowLink = [];
    protected string $_posHelp;
    /**
     * @var array|mixed
     */
    private array $moduleOptionsConf = [];

    abstract function init();

    abstract function generateRoute($sign, $default = null, $params = []);//生成路由的方法由BaseTrait提供

    abstract function beforeTab(Tab $tab);

    abstract function afterTab(Tab $tab, Request $request);

    abstract function beforeTitleForm(Form $form);

    abstract function beforeLinkForm(Form $form);

    abstract function beforeSortForm(Form $form);

    abstract function beforeShareForm(Form $form);

    abstract function beforeDisplayForm(Form $form);

    abstract function beforeReasonForm(Form $form);

    abstract function beforeProfileForm(Form $form);

    abstract function saveModule(Request $request, $baseInfoId);

    abstract function delModule($id);

    abstract function relationCheck($account, $relation);

    abstract function extendGrid($list);

    abstract function extendSaveBaseInfo(Request $request);

    public function __destruct()
    {

    }


    protected function setPositionConf($positionId)
    {
        $this->positionId = $positionId;
        $this->afterSetPositionId();
    }

    protected function getPositionConf($filed = null, $default = null)
    {
        if (is_null($filed)) return $this->positionConf;
        return $this->positionConf[$filed] ?? $default;
    }

    protected function getPositionConfOptions($filed = null, $default = [])
    {
        $options = $this->moduleOptionsConf;
        if (is_null($filed)) return $options;
        return $options[$filed] ?? $default;
    }

    protected function generatePosPosition(): array
    {
        $arr = [];
        $card_pos = $this->getPositionConfOptions('card_pos', '');
        $card_pos = $card_pos ?: $this->getPositionConfOptions('pos', '');
        if ($card_pos) {
            $rel_pos = $this->getPositionConfOptions('rel_pos', '');
            $rel_pos_arr = explode(',', $rel_pos);
            $pos = is_numeric($card_pos) ? range(1, $card_pos) : explode(',', $card_pos);
            $arr = array_combine($pos, $pos);
            //如果是占位编辑,只有占位的 pos
            if ($this->relId > 0) {
                return [$this->base_field_pos => $this->base_field_pos];
            }
            //如果 is_admin 为 false, 需要剔除
            if ($rel_pos && !$this->is_admin) {
                foreach ($rel_pos_arr as $i) {
                    unset($arr[$i]);
                }
            }
        }
        return $arr;
    }

    /**
     * @throws Exception
     */
    protected function posCheck($pos, $title = '展示位置')
    {
        //这是一个占位的校验
        //如果在占位项目中编辑,位置必须与占位的位置一致
        //如果开启了占位,除非有指定管理员权限才能跳过校验,校验规则如下
        //如果指定了[占位开放位置],提示这些位置需要占位才能使用
        //如果没有指定[占位开放位置],提示管理员权限才能使用
        if ($pos <= 0)  throw new Exception($title . '必选大于0');
        $rel_pos = $this->getPositionConfOptions('rel_pos');

        if ($this->relId) {
            if ($this->base_field_pos != $pos) throw new Exception($title . '不允许变更');
        } else {
            if (!$this->is_admin) {
                if (empty($rel_pos)) {
                    throw new Exception("配置需到占位系统进行占位");
                } else {
                    $rel_pos_arr = explode(',', $rel_pos);
                    if (in_array($pos, $rel_pos_arr)) throw new Exception("[$rel_pos]这些位置需要占位才能使用");
                }
            }
        }
    }

    protected function getPositionImgConf(): array
    {
        $conf = $this->getPositionConfOptions();
        if (empty($conf)) return [];
        $response = [];
        if (!empty($conf['img_size'])) {
            $response['img_size'] = ['operator' => '<', 'value' => $conf['img_size']];
        }
        if (!empty($conf['img_area'])) {
            $areas = explode(";", $conf['img_area']);
            $img_area = [];
            foreach ($areas as $area) {
                $arr = explode(',', $area);
                $temp = [];
                if (isset($arr[0])) $temp['w'] = trim($arr[0]);
                if (isset($arr[1])) $temp['h'] = trim($arr[1]);
                if ($temp) $img_area[] = $temp;
            }
            if ($img_area) $response['img_area'] = $img_area;
        }
        return $response;
    }


    /**
     * @throws Exception
     */
    public function formRulesValid($inputRules, $pos = null)
    {
        $check = $inputRules['check'] ?? 0;
        if (!$check) return;

        //图片规则
        $rules = $this->getPositionImgConf();

        foreach ($rules as $key => $rows) {
            switch ($key) {
                case 'img_size':
                    $title = '当前图片';
                    foreach ($rows as $k => $row) {
                        if (!is_null($pos) && ($k != $pos)) continue;
                        $title = empty($row['label']) ? '当前图片' : $row['label'];
                    }
                    $input = $inputRules['img_size'] ?? 0;
                    $bool = version_compare($input, $rows['value'], $rows['operator']);
                    if (!$bool) throw new Exception($title . '大小需要 ' . htmlentities($rows['operator']) . ' ' . self::conversion($rows['value']) . ' 当前图片大小 ' . self::conversion($input));
                    break;
                case 'img_area':
                    $input_w = $inputRules['img_w'] ?? '0';
                    $input_h = $inputRules['img_h'] ?? '0';
                    $allow = [];
                    $throw = true;
                    $title = '当前图片';
                    foreach ($rows as $k => $row) {
                        if (!is_null($pos) && ($k != $pos)) continue;
                        $title = empty($row['label']) ? '当前图片' : $row['label'];
                        $allow[] = isset($row['h']) ? "[{$row['w']} x {$row['h']}]" : "宽度限制{$row['w']}";
                        if ($input_w == $row['w']) $throw = false;
                        if (isset($row['h']) && ($input_h != $row['h'])) $throw = true;
                        if (!$throw) break;
                    }

                    if ($throw) throw new Exception($title . "宽高[$input_w x $input_h],图片宽高允许: " . implode(' ', $allow));
                    break;
            }
        }
    }

    public function bannerForm(Form $form, $column = 'base.pic_id', $label = 'banner图')
    {
        $options = $this->getPositionImgConf();
        $form->bh('rules.img_w');
        $form->bh('rules.img_h');
        $form->bh('rules.img_size');
        $form->imgUpload($column, $label)
            ->help($this->formImgHelp())
            ->setImgSizeInputId("rules.img_size")
            ->setImgWidthInputId("rules.img_w")
            ->setImgHeightInputId("rules.img_h");
        if ($options) $form->radio('rules.check', $label . '校验')->options(['否', '是'])->default(1);
    }
    public function formImgHelp($pos = null, $separator = ' ; '): string
    {
        $help = [];
        $rules = $this->getPositionImgConf();
        foreach ($rules as $key => $rows) {
            switch ($key) {
                case 'img_size':
                    $help[] = '图片大小规格 : ' . htmlentities($rows['operator']) . ' ' . self::conversion($rows['value']);
                    break;
                case 'img_area':
                    $allow = [];
                    foreach ($rows as $k => $row) {
                        if (is_null($pos)) $allow[] = isset($row['h']) ? "[{$row['w']} x {$row['h']}]" : "宽度限制{$row['w']}";
                        if (is_numeric($pos) && ($k == $pos)) {
                            $allow[] = "[{$row['w']} x {$row['h']}]";
                            if (!empty($row['desc'])) $allow[] = $row['desc'];
                        }
                    }
                    $help[] = empty($allow) ? '' : "图片宽高规格 : " . implode($separator, $allow);

                    break;
            }
        }

        return implode($separator, $help);
    }

    public static function conversion($size): string
    {
        $unit = ['B','KB','MB','GB','TB','PB'];
        //指数
        $i = $size < 1024 ? 0 : floor(log($size,1024));
        //基数
        $operand = pow(1024, $i);

        return round($size / $operand,2) . $unit[$i];
    }

    public function getRouteParams()
    {
        return $this->relId ? [$this->positionId, $this->relId] : [$this->positionId];
    }

    public function relationPostCheck($baseInfo)
    {
        if (!$this->relId) return;

        if ($baseInfo['start_show_time'] < $this->relation['start_show_time']) throw new Exception('展示时间限制');

        if ($baseInfo['end_show_time'] > $this->relation['end_show_time']) throw new Exception('展示时间限制');

        $shareMap = [
            MPositionProjectRelations::SHARE_OK => MPositionBaseInfo::IS_SHARE,
            MPositionProjectRelations::SHARE_NO => MPositionBaseInfo::IS_NOT_SHARE,
        ];

        if (AdConfManagement::displayField(AdConfManagement::FIELD_DISABLED_SHARE) && $baseInfo['is_share'] != $shareMap[$this->relation['is_share']]) throw new Exception('共享限制');

    }

    /**
     * 初始化配置,包括路由,文件配置,资源位功能
     * 权限校验,包括没有资源位 id,开启占位关联,占位系统权限校验
     *
     * @throws Exception
     */
    public function initModuleInfo(Request $request = null)
    {
        $this->listRoute = $this->generateRoute($this->relId ? 'projectList' : 'list');
        if (!empty($request) && !empty($request->input('pos'))) $this->listRoute = $this->listRoute . "?pos=" . $request->input('pos');
        $this->saveRoute = $this->relId ? 'projectSave' : 'save';
        $this->copyRoute = $this->relId ? 'projectCopy' : 'copy';
        $conf = $this->positionConf = AdPositionManagement::getConfById($this->positionId);
        $this->en_name = $conf['en_name'] ?? '';
        $this->moduleTitle = $conf['title'] ?? '未命名';
        $this->moduleTitle4List = $this->moduleTitle;
        $this->moduleRel = $conf['rel'] ?? MPosition::REL_CLOSE;
        $this->moduleTab = $conf['app_tab'] ?? ConstInterface::APP_TAB1;
        $this->moduleOptionsConf = $conf['options'] ?? [];

        $funConf = $conf['drop_version'] ?: null;
        $super_role = empty($conf['super_role']) ? [] : explode(',', $conf['super_role']);
        $op_roles = empty($conf['op_roles']) ? [] : explode(',', $conf['op_roles']);

        if (!empty($op_roles)) $this->is_operator = Admin::user()->inRoles($op_roles);
        $this->is_admin = \Biz\service\advertisement\AdCacheManagement::isAdmUser(Admin::user()->username) || ($super_role ? Admin::user()->inRoles($super_role) : Admin::user()->isAdministrator());
        //功能拆解
        if (is_null($funConf)) {
            AdConfManagement::setConf();
        } else {
            AdConfManagement::setConf(AdConfManagement::FIELD_ALL ^ $funConf);
        }
        //列表页对配置的功能描述
        $this->conf_message = AdConfManagement::showConf($funConf);

        if ($this->positionId == 0) throw new Exception('资源位id参数不正确');
        //对 pos 的描述处理
        $card_pos = $this->getPositionConfOptions('card_pos', '') ?: $this->getPositionConfOptions('pos');
        $rel_pos = $this->getPositionConfOptions('rel_pos', '');
        if ($card_pos) {
            $help[] = is_numeric($card_pos) ? "可选1-{$card_pos}任意数字" : "可选{$card_pos}任意数字";
            if ($rel_pos) {
                $help[] = "配置位置{$rel_pos}需要去占位系统进行占位 <a target='_blank' href='https://puck.haohaozhu.me/taskMap'>点击此处</a>";
            }
            $this->_posHelp = "<span style='color: red'>" . implode('<br/>', $help) . "</span>";
            $posOptions = $this->generatePosPosition();
            $this->base_field_pos = current($posOptions);
        }
        //对 link 处理
        $cardAllowLink = $this->getPositionConfOptions('card_link');
        if ($cardAllowLink) {
            $this->cardAllowLink = $cardAllowLink;
        }
        $bannerAllowLink = $this->getPositionConfOptions('banner_link');
        if ($bannerAllowLink) {
            $this->bannerAllowLink = $bannerAllowLink;
        }
        //开启占位
        if ($this->relId) {
            if ($this->moduleRel == MPosition::REL_CLOSE) throw new Exception('未开启占位关联');
            //查询占位信息和占位项目
            $this->relation = MPositionProjectRelations::get('*', ['id' => $this->relId, 'project_status' => MPositionProjectRelations::PROJECT_STATUS_OK]);
            $this->project = empty($this->relation['project_id']) ? null : MPositionProject::get('*', ['id' => $this->relation['project_id'], 'project_status' => MPositionProject::PROJECT_STATUS_OK]);
            $hasKeywords = in_array($this->relation['ad_id'], \Biz\model\advertisement\MPositionAdRule::uniqueAd());

            $shareMap = [
                MPositionProjectRelations::SHARE_OK => MPositionBaseInfo::IS_SHARE,
                MPositionProjectRelations::SHARE_NO => MPositionBaseInfo::IS_NOT_SHARE,
            ];
            $this->base_field_share = $this->relation['is_share'] ? $shareMap[$this->relation['is_share']] : $this->base_field_share;
            if ($this->positionId == PositionConstInterface::HOME_CAROUSEL_V5) {
                $ext = $request ? $request->input('base.ext_type') : null;
                //独占逻辑判断
                if ($this->base_field_share == MPositionBaseInfo::IS_SHARE && $ext == 1) {
                    throw new Exception('占位时设置共享，则在轮播图设置的时候不能独占');
                }
            }
//            //exclusive_map
//            if($this->relation['is_exclusive']){
//                $this->base_field_ext_type = $this->relation['is_exclusive'];
//            }
//            //exclusive_map
            $nameMap = AdPosition::positionAdTypeOptions();
            $project_name = $this->project['project_name'] ?? '查询失败';
            $this->message = [
                '项目名称:' . $project_name,
                '资源位名称:' . ($nameMap[$this->relation['ad_id']] ?? '未设置'),
                '占位时间:' . $this->relation['start_show_time'] . '~' . $this->relation['end_show_time'],
            ];
            if ($hasKeywords) $this->message[] = "关键词:" . $this->relation['ad_unique'];
            if($this->relation['is_exclusive']){
                $this->message[] = "独占";
            }
            $this->tabName = "占位列表";
            //占位系统权限校验
            $this->relationCheck(Admin::user()->username, $this->relation);
        } else {
            $msg = $super_role ? '仅限指定角色' : '仅限超级管理员权限';
            //开启占位进行权限校验,预览可以通过
            if ($this->moduleRel == MPosition::REL_OPEN && !$this->preview && !$this->is_admin) {
                //管理员或者指定角色的管理员可以不占位
                //如果配置了占位开放位置,不做跳转处理
                $rel_pos = $this->getPositionConfOptions('rel_pos');
                if (empty($rel_pos) || empty($this->generatePosPosition())) {
                    throw new Exception($msg, self::REDIRECT_CODE);
                }
            }
        }
    }

    public function getMessageHtml(): string
    {
        return empty($this->message) ? '' : \Doraemon\tools\Msg2Admin::html($title = '提示', implode('<br/>', $this->message), 'warning');
    }

    public function defaultBaseInfo(Request $request)
    {
        return [
            'play_times'      => BaseModule::GIF_PLAY_TIMES_DEFAULT,
            'close_type'      => $this->base_field_close_type,
            'ext_type'        => $this->base_field_ext_type,
            'pos'             => $this->base_field_pos ?: 0,
            'is_share'        => $this->base_field_share,
            'rel_id'          => $this->relId,
            'position_id'     => $this->positionId,
            'show_type'       => MPositionBaseInfo::SHOW_TYPE_TIME,
            'start_show_time' => $this->relation['start_show_time'] ?: date('Y-m-d 00:00:00', strtotime('1 day')),
            'start_show_time2' => $this->relation['start_show_time'] ?: date('Y-m-d 00:00:00', strtotime('1 day')),
            'end_show_time'   => $this->relation['end_show_time'] ?: date('Y-m-d 23:59:59', strtotime('1 day')),
        ];
    }

    protected function extendDefaultBaseInfo()
    {
        return [];
    }

    public function defaultUserProfile()
    {
        return [];
    }

    public function __construct()
    {
        parent::__construct();

        \Encore\Admin\Form::extend('bh', \App\Admin\Extensions\Form\BackHidden::class); // 图片上传组件

        $this->init();
    }


    public function extendList(Grid $grid)
    {
        $grid->column('pic_url', '图片')->image("", 120);
    }

    public function condition($request)
    {
        $response = [];
        if (isset($request['end_show_time']['start']) && strlen($request['end_show_time']['start'])) {
            $response['end_show_time[>=]'] = $request['end_show_time']['start'];
        }

        if (isset($request['end_show_time']['end']) && strlen($request['end_show_time']['end'])) {
            $response['end_show_time[<=]'] = $request['end_show_time']['end'];
        }

        if (!empty($request['pos'])) $response['pos'] = explode(",", $request['pos']);

        if (!empty($request['id'])) $response['id'] = explode(",", $request['id']);

        if (isset($request['client_uid']) && strlen($request['client_uid'])) $response['client_uid'] = explode(",", $request['client_uid']);

        if (!empty($request['ext_type'])) $response['ext_type'] = $request['ext_type'];

        return $response;
    }

    protected function initRequest(Request $request)
    {
        //初始化查询参数
        if (!$request->input('end_show_time')) {
            $request->merge([
                'end_show_time' => [
                    'start' => date('Y-m-d H:i:s'),
                ]
            ]);
        }
        return $request;
    }

    protected function checkInit($condition)
    {
        unset($condition['pos'], $condition['ext_type']);
        if (isset($condition['end_show_time[>=]']) && date('Ymd') == date("Ymd",strtotime($condition['end_show_time[>=]']))) unset($condition['end_show_time[>=]']);
        if (empty($condition)) return true;
    }

    public function copyOneAd(Request $request, Content $content, $position_id = 0, $rel_id = 0, $id = 0)
    {
        $this->setPositionConf($position_id);
        $this->relId = $rel_id;
        $this->id = $id;

        return $this->copy($request, $content, $id);
    }

    public function copyOne(Request $request, Content $content, $position_id = 0, $id = 0)
    {
        $this->setPositionConf($position_id);

        return $this->copy($request, $content, $id);
    }

    public function createOneAd(Request $request, Content $content, $position_id = 0, $rel_id = 0, $id = 0)
    {
        $this->setPositionConf($position_id);
        $this->relId = $rel_id;
        $this->id = $id;

        return $this->create($request, $content, $id);
    }

    public function createOne(Request $request, Content $content, $position_id = 0, $id = 0)
    {
        $this->setPositionConf($position_id);
        $this->id = $id;

        return $this->create($request, $content, $id);
    }

    public function saveOne(Request $request, $position_id = 0, $rel_id = 0)
    {
        $this->setPositionConf($position_id);
        $this->relId = $rel_id;

        return $this->save($request, $position_id);
    }

    public function deleteOne($position_id = 0, $rel_id = 0, $id = 0)
    {
        if ($id == 0) {
            $id = $rel_id;
            $rel_id = 0;
        }
        $this->setPositionConf($position_id);
        $this->relId = $rel_id;
        //删除前没有校验权限
        return $this->delete($id);
    }

    public function preview(Request $request, Content $content, $position_id = 0, $rel_id = 0)
    {
        $this->preview = true;

        return $this->list($request, $content, $position_id, $rel_id);
    }

    public function view(Request $request, Content $content, $position_id = 0)
    {
        $this->preview = true;

        $this->message = [
            '列表仅供查看',
            '配置需到占位系统进行占位 <a target="_blank" href="https://puck.haohaozhu.me/taskMap">点击此处</a>',
        ];

        return $this->list($request, $content, $position_id);
    }

    public function list(Request $request, Content $content, $position_id = 0, $rel_id = 0)
    {
        //传入的资源位类型id
        $this->setPositionConf($position_id);
        $this->relId = intval($rel_id);

        try {
            //资源位配置信息
            $this->initModuleInfo();
            $tab = new Tab();
            $request = $this->initRequest($request);
            $condition = $this->condition($request->all());
            $init = $this->checkInit($condition);
            $page = $request->input('page', 1);
            $pageSize = $request->input('per_page', AdmOperationModule::PAGE_SIZE);
            $option = empty($condition) ? 0 : self::$expand;
            $condition['position_id'] = $this->positionId;
            $selfProject = false;
            //如果是项目id,只展示项目中的资源位
            if ($rel_id > 0 && !$this->preview) {
                $condition['rel_id'] = $rel_id;
                $selfProject = true;
            }

            $total = null;
            if ($init) {
                $list = AdmOperationModule::getBaseListByPositionId($condition, $selfProject);
                $option = $option | self::$disPagination;
            } else {
                list($list, $total) = AdmOperationModule::getFailListByPositionId($condition, $page, $pageSize);
                $option = $option | self::$disSortable;
            }

            $list = $this->extendGrid($list);

            $gridModel = new GridDataModel($list, $total);
            $detailGrid = $this->baseGrid($gridModel, $option);

            $this->beforeTab($tab);

            $tab->addLink($this->tabName, $this->listRoute, !$this->preview);

            $this->afterTab($tab, $request);

            if ($this->relId) $tab->addLink('全部列表', $this->generateRoute($this->previewRoute), $this->preview);

            $header = $this->moduleTitle4List;
            if ($this->conf_message) {
                $this->message = array_merge([$this->conf_message, "<hr/>"], $this->message);
            }

            return $content
                ->header($header)
                ->description(' ')
                ->breadcrumb(['text' => 'APP固定资源位', 'url' => route('position.main', ['tab' => $this->moduleTab])], ['text' => $header])
                ->row($this->getMessageHtml())
                ->row($tab)
                ->row($detailGrid);
        } catch (Exception $e) {
            $error = new MessageBag([
                'title' => $e->getMessage()
            ]);
            if ($e->getCode() == self::REDIRECT_CODE) {
                return redirect($this->generateRoute($this->viewRoute));
            }
            return redirect(route('position.main'))->with(compact('error'));
        }
    }

    public static $disFilter = 1;
    public static $disSortable = 2;
    public static $disPagination = 4;
    public static $expand = 8;

    public static function searchUserProfile()
    {

    }

    protected function baseGrid($gridModel, $option = 0)
    {
        return Admin::grid($gridModel,
            function (Grid $grid) use ($gridModel, $option) {
                if (self::$disFilter & $option) $grid->disableFilter();
                $grid->disableExport();
                $grid->disableCreateButton();
                $grid->disableRowSelector();
                $grid->paginate($gridModel->getPerPage());
                if (self::$disPagination & $option) $grid->disablePagination();

                //添加按钮
                $grid->tools(function (Grid\Tools $tool) use ($grid) {
                    $help_link = "https://confluence.haohaozhu.me/pages/viewpage.action?pageId=38142149";
                    $tool->append('<div class="btn-group download" style="margin-right: 10px">
    <a class="btn btn-sm btn-twitter" href="' . $help_link . '" target="_blank" title="操作指南"><i class="fa fa-question-circle-o"></i><span class="hidden-xs"> 操作指南</span></a>
</div>');
                    $createUrl = \Illuminate\Support\Facades\Request::input('pos') > 0
                        ? $grid->getCreateUrl() . "?pos=" . \Illuminate\Support\Facades\Request::input('pos')
                        : $grid->getCreateUrl();
                    if (!$this->preview && $this->is_operator) $tool->prepend('<div class="btn-group pull-right grid-create-btn" style="margin-right: 10px">
    <a href="' . $createUrl . '" class="btn btn-sm btn-success" title="新增">
        <i class="fa fa-plus"></i><span class="hidden-xs">&nbsp;&nbsp;新增</span>
    </a>
</div>');
                });



                $idRow = $grid->column('id', 'ID');

                if (!(self::$disSortable & $option) && (!$this->preview) && $this->is_operator) $idRow->sort();

                $this->extendList($grid);

                $grid->column('show_desc', '展示状态')->display(function ($title, Grid\Column $column) {
                    return $this->show_desc;
                });

                if (AdConfManagement::displayField(AdConfManagement::FIELD_LINK)) $grid->column('link', '链接地址')->width(250)->linkSelect(false, null, false);

                if (AdConfManagement::displayField(AdConfManagement::FIELD_DISABLED_USER_PROFILE)) $grid->column('user_profile', '分群信息')->userProfile();

                if (AdConfManagement::displayField(AdConfManagement::FIELD_DISABLED_SHARE)) $grid->column('share_desc', '共享')->display(function ($title, Grid\Column $column) {
                    if ($this->is_share == MPositionBaseInfo::IS_SHARE) {
                        return $column->label('success');
                    } else {
                        return $column->label('warning');
                    }
                });


                if (AdConfManagement::displayField(AdConfManagement::FIELD_DISABLED_REASON)) $grid->column('remark', '运营/商业备注')->display(function ($title, Grid\Column $column) {
                    $html = [
                        "投放原因:" . MPositionBaseInfo::REASON_MAP[$this->reason],
                        "投放目的:" . (MPositionBaseInfo::AIM_MAP[$this->aim] ?? ''),
                        "备注:" . $this->remark,
                    ];

                    return implode("<br/>", $html);
                });

                $grid->column('', 'ctr')->display(function () {
                    return $this->rel_id ? "📅" : "";
                })->expand(function ($model) {
                    return new Table(['日期', '曝光次数', '点击次数', '曝光用户数(去重)', '点击用户数(去重)', 'ctr'], $this->daily_ctr);
                });
                $grid->column('admin_id', '操作人')->display(function () {
                    return $this->admin_id ? Admin::user()->find($this->admin_id)->name : '-';
                });
                $that = $this;
                $preview = $this->preview;
                $is_operator = $this->is_operator;
                //筛选
                $grid->filter(function (Grid\Filter $filter) use ($option) {
                    // 去掉默认的id过滤器
                    $filter->disableIdFilter();

                    $filter->column(1 / 2, function (Grid\Filter $filter) {
                        $filter->equal('id', '配置id')->placeholder('多个id,隔开');
                        if ($this->filter_field_pos) $filter->equal('pos', '位置');
                        if ($this->filter_field_uid) $filter->equal('client_uid', '客户uid');
                    });

                    $filter->column(1 / 2, function (Grid\Filter $filter) {

                        //时间筛选
                        $filter->between('end_show_time', '截止日期')->datetime()->condition(['end_show_time' => \Illuminate\Support\Facades\Request::input('end_show_time')]);
                    });

                    //条件展开
                    if (self::$expand & $option) $filter->expand();
                });
                $grid->actions(function (Grid\Displayers\Actions $actions) use ($that, $preview, $is_operator) {
                    if ($preview || !$is_operator) {
                        $actions->disableAll();
                    } else {
                        //隐藏过期的编辑
                        if ($actions->row->label == 'danger') {
                            $actions->disableEdit();
                        }

                        //复制功能
                        $copyUrl = $that->generateRoute($that->copyRoute, null, array_merge($that->getRouteParams(), [$actions->row->id]));
                        $actions->append('<a class="fa fa-copy" href="' . $copyUrl . '">复制</a>');

                        //指定用户的metabase查询跳转
                        $ctr = in_array(Admin::user()->id, [30, 131, 88]) ? $this->row->ctr_rand : '';
                        if ($ctr) {
                            $actions->append('<a class="fa fa-line-chart" href="javascript:layer.open({
                type: 2,
                title: \'曝光数据\',
                maxmin: true,
                shade: 0,
                area: [\'900px\', \'500px\'],
                content: \'' . $ctr . '\'
            });">CTR</a>');
                        }
                    }
                });
            });
    }

    /**
     * @throws Exception
     */
    public function copy(Request $request, Content $content, $id = 0)
    {
        //资源位配置信息
        $this->initModuleInfo();

        //基础信息
        $info = $this->getCreateData($id, $request);
        $info['base']['copy_id'] = $id;
        unset($info['base']['id']);

        //基础信息表单
        $form = $this->createForm($request, $info);
        $tab = new Tab();
        $tab->add('基础信息', $form);
        $header = '复制' . $this->moduleTitle;
        //复制时校验
        //如果有指定占位权限,但是没有权限时提示操作失败信息
        if (!$this->is_admin && $this->getPositionConfOptions('rel_pos')) {
            if (!in_array($info['base']['pos'], $this->generatePosPosition())) {
                $error = new MessageBag([
                    'title' => '占位配置不允许复制'
                ]);
                return back()->with(compact('error'));
            }
        }

        //加强复制页面的提示
        admin_toastr('这是复制信息...', 'warning', ['timeOut' => 5000, 'positionClass' => 'toast-top-center']);

        return $content->header($header)->description(' ')->breadcrumb(
            ['text' => '资源位管理', 'url' => route('position.main')],
            ['text' => $this->moduleTitle4List, 'url' => $this->listRoute], ['text' => $header])
            ->row($this->getMessageHtml())
            ->row($tab);
    }

    /**
     * @throws Exception
     */
    public function create(Request $request, Content $content, $id = 0)
    {
        //资源位配置信息
        $this->initModuleInfo($request);

        //获取资源位信息
        $info = $this->getCreateData($id, $request);

        //创建表单
        $form = $this->createForm($request, $info);

        //如果有指定占位权限,但是没有权限时提示操作失败信息
        if ($id > 0 && !$this->is_admin && $this->getPositionConfOptions('rel_pos')) {
            if (!in_array($info['base']['pos'], $this->generatePosPosition())) {
                $error = new MessageBag([
                    'title' => '占位配置不允许编辑'
                ]);
                return back()->with(compact('error'));
            }
        }

        //组合创建页面
        $tab = new Tab();
        $tab->add('基础信息', $form);
        $header = ($id > 0 ? '编辑' : '添加') . $this->moduleTitle;
        return $content->header($header)->description(' ')
            ->breadcrumb(
            ['text' => '资源位管理', 'url' => route('position.main')],
            ['text' => $this->moduleTitle4List, 'url' => $this->listRoute], ['text' => $header]
            )
            ->row($this->getMessageHtml())
            ->row($tab);
    }

    public function getCreateData($id, $request)
    {
        //基础信息
        $base = $id > 0 ? AdmOperationModule::getBaseInfoById($id, $this->relation) : $this->defaultBaseInfo($request);

        $info = $id > 0 ? AdmOperationModule::getExtInfo($this->en_name, $base) : $this->extendDefaultBaseInfo();

        //分群信息
        $user_profile = $id > 0 ? AdmOperationModule::getPositionRulesById($id, MPositionRules::MODULE_TYPE_POSITION, true) : $this->defaultUserProfile();
        //独占信息更新
        if($this->relation['is_exclusive']){
            $base['ext_type'] = $this->relation['is_exclusive'];
        }
        //独占信息更新

        //扩展信息
        $base['sort'] = empty($base) ? MPositionBaseInfo::SORT_TYPE_BOTTOM : '-1';
        $info['base'] = $base;
        $info['user_profile'] = $user_profile;

        return $info;
    }

    /**
     * 基础信息表单
     * @param       $request
     * @param array $info
     * @return Form
     */
    private function createForm($request, $info = [])
    {
        //排序初始值
        $admSortTypeMap = MPositionBaseInfo::ADM_SORT_TYPE_MAP;
        if (!empty($info['base']['id'])) $admSortTypeMap['-1'] = '保持不变';
        $info['base']['sort'] = empty($info['base']['id']) ? MPositionBaseInfo::SORT_TYPE_BOTTOM : -1;
        $form = new Form($info);
        $form->disableReset();
        $form->bh('base.id');
        $form->bh('base.module_id');
        $form->bh('base.rel_id');
        $form->bh('base.copy_id');
        $form->select('base.position_id', '资源位置')
            ->options([$this->positionId => $this->moduleTitle])
            ->readOnly()
            ->required();
        $this->beforeTitleForm($form);
        if (AdConfManagement::displayField(AdConfManagement::FIELD_SHOW_TIME)) {
            $form->radio('base.show_type', '展示时间')
                ->options(MPositionBaseInfo::SHOW_TYPE_MAP)
                ->when(MPositionBaseInfo::SHOW_TYPE_TIME, function (Form $form) {
                    $form->dateTimeRange('base.start_show_time', 'base.end_show_time', ' ');
                })->when(MPositionBaseInfo::SHOW_TYPE_ALWAYS, function (Form $form) {
                    $form->datetime('base.start_show_time2', '开始展示时间');
                });
        }
        $this->beforeSortForm($form);
        if (AdConfManagement::displayField(AdConfManagement::FIELD_SORT)) $form->radio('base.sort', '默认排序')->options($admSortTypeMap)->help('同时生效的多个共享banner，会进行排序');

        $this->beforeShareForm($form);
        if (AdConfManagement::displayField(AdConfManagement::FIELD_DISABLED_SHARE)) {
            if ($this->relId) {
                $form->bh('base.is_share');
            } else {
                $form->radio('base.is_share', '是否共享')->options(MPositionBaseInfo::ADM_IS_SHARE_MAP)->help('同时生效的多个共享banner，会以同样的概率展示给符合条件的用户');
            }
        }

        $this->beforeDisplayForm($form);
        if (AdConfManagement::displayField(AdConfManagement::FIELD_DISPLAY)) {
            $form->userProfile('user_profile')->generateShowStyle('action', '展示方式', array_combine(range(1, 9), range(1, 9)));
        }

        $this->beforeReasonForm($form);
        if (AdConfManagement::displayField(AdConfManagement::FIELD_DISABLED_REASON)) {
            $form->radio('base.reason', '投放原因')
                ->options(MPositionBaseInfo::REASON_MAP)
                ->default(MPositionBaseInfo::REASON_TYPE_OPERATE)
                ->when(MPositionBaseInfo::REASON_TYPE_BUSINESS, function (Form $form) {
                    $form->text('base.client_uid', '客户uid')->help('如果客户已入驻好好住，请填写uid，以便统计；没有可不填');
                    $form->text('base.client_nick', '客户名称')->help('请填写客户名称，以便统计');
                })->when(MPositionBaseInfo::REASON_TYPE_KA, function (Form $form) {
                    $form->text('base.client_uid', '客户uid')->help('请填写设计师uid，以便统计');
                });

            $form->select('base.aim', '投放目的')->options(MPositionBaseInfo::AIM_MAP)->default(-1)->required()
            ->help("<a target='_blank' href='https://alidocs.dingtalk.com/i/nodes/ZgpG2NdyVXp0bY4OTxgXvLGgVMwvDqPk# 「投放目的操作手册与指南」'>投放目的操作手册与指南</a>");
            $help = [
                MPositionBaseInfo::REASON_TYPE_BUSINESS => MPositionBaseInfo::REASON_MAP[MPositionBaseInfo::REASON_TYPE_BUSINESS] . ':建议描述素材内容，以便统计；可不填',
                MPositionBaseInfo::REASON_TYPE_KA       => MPositionBaseInfo::REASON_MAP[MPositionBaseInfo::REASON_TYPE_KA] . ':建议填写客户名称和套餐类型，以便统计；可不填',
                MPositionBaseInfo::REASON_TYPE_OPERATE  => MPositionBaseInfo::REASON_MAP[MPositionBaseInfo::REASON_TYPE_OPERATE] . ':建议填写投放部门和素材内容，以便统计；可不填',
                MPositionBaseInfo::REASON_TYPE_NEW_USER => MPositionBaseInfo::REASON_MAP[MPositionBaseInfo::REASON_TYPE_NEW_USER] . ':建议描述素材内容，以便统计；可不填',
            ];
            $form->textarea('base.remark', '备注')->help(implode('<br/>', $help));
        }

        $this->beforeLinkForm($form);
        if (AdConfManagement::displayField(AdConfManagement::FIELD_LINK)) {
            $conf = $this->getPositionConf('style_type', '');
            if ($conf !== 'custom_card') {
                $form->multiLinkSelect('base.link', '跳转链接', $this->bannerAllowLink);
            }
        }

        $this->beforeProfileForm($form);
        if (AdConfManagement::displayField(AdConfManagement::FIELD_DISABLED_USER_PROFILE)) $form->userProfile('user_profile', '用户分群')->options()->generate();

        $form->action($this->generateRoute($this->saveRoute, $request->getPathInfo()));

        return $form;
    }

    /**
     * 通用保存信息控制器
     * @param Request $request
     * @param int     $position_id
     * @return \Illuminate\Http\RedirectResponse
     */
    public function save(Request $request, $position_id = 0)
    {
        $position_id = $position_id > 0 ? $position_id : $this->positionId;
        $baseInfo = $request->input('base', []);
        $baseInfo['position_id'] = $position_id;
        $baseInfo['link_type'] = $baseInfo['link']['link_type'] ?? '';
        $baseInfo['link_params'] = json_encode($baseInfo['link']['link_params'] ?? [], JSON_UNESCAPED_UNICODE);
        $baseInfo['admin_id'] = Admin::user()->id;
        $id = $baseInfo['id'] ?? 0;

        //按模块分别存储数据
        try {
            //资源位配置信息
            $this->initModuleInfo($request);

            MPositionBaseInfo::action(function () use ($baseInfo, $request) {
                //如果是占位系统校验时间段
                $this->relationPostCheck($baseInfo);

                //添加扩展保存信息
                $baseInfo = $this->extendSaveBaseInfo($request) + $baseInfo;

                //添加基本信息
                $baseInfoId = AdmOperationModule::addBaseInfo($baseInfo);

                //添加分群信息
                $userProfile = $request->input('user_profile', []);

                AdmOperationModule::addUserProfile($baseInfoId, $userProfile);

                //添加扩展模块信息
                $this->saveModule($request, $baseInfoId);

            });

            //重新设置缓存
            CPositionBaseInfo::admDelItem($baseInfo['position_id'], $id);

            $success = new MessageBag([
                'title' => ($id > 0 ? '编辑' : '添加') . '成功'
            ]);

            return redirect($this->listRoute)->with(compact('success'));
        } catch (Exception $e) {
            $error = new MessageBag([
                'title' => '操作失败,信息:' . $e->getMessage()
            ]);
            return back()->withInput()->with(compact('error'));
        }
    }


    /**
     * 通用删除方法,主表信息需要存在position_base_info
     * @param int $id
     * @return \Illuminate\Http\JsonResponse
     * @throws Exception
     */
    public function delete($id = 0)
    {
        //资源位配置信息
        $this->initModuleInfo();
        $status = true;
        $message = "删除成功";
        try {
            $info = MPositionBaseInfo::get(['info_status', 'position_id', 'pos'], ['id' => $id]);
            if (empty($info)) throw new Exception('删除信息不存在');
            //如果有指定占位权限,但是没有权限时提示操作失败信息
            if (!$this->is_admin && $this->getPositionConfOptions('rel_pos')) {
                if (!in_array($info['pos'], $this->generatePosPosition())) throw new Exception('位置权限不足');
            }

            if (in_array($info['info_status'], [MPositionBaseInfo::STATUS_NORMAL, MPositionBaseInfo::STATUS_RELEASE])) {
                AdmOperationModule::delModule($id);
            }

            //清除缓存
            CPositionBaseInfo::admDelItem($info['position_id'], $id);

            //删除模块信息
            $this->delModule($id);

        } catch (Exception $e) {
            $status = false;
            $message = "操作失败,信息:" . $e->getMessage();
        }

        return response()->json(compact('status', 'message'));
    }

    /**
     * 项目占位的排序
     * @param Request $request
     * @return mixed
     */
    public function categorySort(Request $request)
    {
        $sortInfo = $request->input('sort');
        $ids = array_keys($sortInfo);

        if (empty($ids)) return;

        $rs = MPositionBaseInfo::select('*', ['id' => $ids]);
        $sort = array_column($rs, 'sort');
        $position_id = $rs[0]['position_id'] ?? 0;
        sort($sort);

        foreach ($ids as $k => $id) {
            $s = $sort[$k];
            AdmOperationModule::saveModuleProjectSort($id, $s);
        }
        //重新设置缓存
        CPositionBaseInfo::admDelItem($position_id, $ids);
    }

    public function sort(Request $request)
    {
        $sortInfo = $request->input('sort');
        $keys = array_keys($sortInfo);
        $position_id = MPositionBaseInfo::get('position_id', ['id' => current($keys)]);
        AdmOperationModule::saveModuleSort($position_id, $sortInfo);
        //重新设置缓存
        CPositionBaseInfo::admDelItem($position_id, $keys);
    }

    protected function afterSetPositionId()
    {
    }
}
